const bcrypt = require('bcrypt');
const {User, AdvisorFavorite} = require('../model/User');
const Advisor = require('../model/Advisor');
const {isValidDateString, isValidPhoneNumber, isValueInEnum} = require("../tool/function");
const Service = require('../model/Service')
const OrderComment = require('../model/Comment')
const {USER_TYPE, CONTRYCODE, } = require("../model/other/enums");
const ApiError = require("../tool/utils/api_error");
const { Op, Sequelize } = require('sequelize');



async function registerService({ phoneNumber, countryCode, password, type }) {
    if(!isValidPhoneNumber(phoneNumber, countryCode) || !isValueInEnum(CONTRYCODE, countryCode))
        throw ApiError.BadRequest('手机号格式错误')
    if (!isValueInEnum(USER_TYPE, type)) {
        throw ApiError.BadRequest('type 参数必须是 0 或 1');
    }
    //todo 检验密码

    const transaction = await User.sequelize.transaction();
    try {
        // 检查手机号是否已存在
        let existing;
        if (type === USER_TYPE.NORMAL) {
            existing = await User.findOne({ where: { phoneNumber } });
        } else if (type === USER_TYPE.ADVISOR) {
            existing = await Advisor.findOne({ where: { phoneNumber } });
        }

        if (existing) {
            throw ApiError.BadRequest('该手机号已注册');
        }

        // 加密密码
        const hashedPassword = await bcrypt.hash(password, 10);

        // 随机生成用户名
        const userName = Math.floor(Math.random() * 1000000)
            .toString()
            .padStart(6, '0');

        // 创建用户
        let data;
        if (type === USER_TYPE.NORMAL) {
            data = await User.create(
                { userName, phoneNumber, password: hashedPassword, type },
                { transaction }
            );
        } else if (type === USER_TYPE.ADVISOR) {
            data = await Advisor.create(
                { userName, phoneNumber, password: hashedPassword, type },
                { transaction }
            );
        }

        await transaction.commit();

        return {
            id: data.id,
            phoneNumber: data.phoneNumber,
        };
    } catch (error) {
        await transaction.rollback();
        throw error; // 抛出给 route 层捕获
    }
}

async function updateUserProfileService({ id, type, name, dataOfBirth, gender, bio, aboutMe }) {
    if(!isValidDateString(dataOfBirth)) throw ApiError.BadRequest('生日格式不正确');

    const transaction = await User.sequelize.transaction();
    try {
        let data;

        if (type === USER_TYPE.NORMAL) {
            // 普通用户
            data = await User.findByPk(id, {
                attributes: { exclude: ['password'] },
            });
            if (!data) throw ApiError.BadRequest('用户不存在');
        } else if (type === USER_TYPE.ADVISOR) {
            // 顾问
            data = await Advisor.findByPk(id, {
                attributes: { exclude: ['password'] },
            });
            if (!data) throw ApiError.BadRequest('顾问不存在');
        } else {
            throw ApiError.BadRequest('无效的用户类型');
        }

        // 更新字段
        if (name !== undefined) data.user_name = name;
        if (dataOfBirth !== undefined) data.dataOfBirth = dataOfBirth;
        if (gender !== undefined) data.gender = gender;
        if (bio !== undefined) data.bio = bio;
        if (aboutMe !== undefined) data.aboutMe = aboutMe;

        await data.save({ transaction });
        await transaction.commit();

        return data;
    } catch (err) {
        await transaction.rollback();
        throw err;
    }
}

async function getAdvisorListService({ pageSize = 10, offset = 0 }) {
    // 参数转数字
    pageSize = Number(pageSize);
    offset = Number(offset);

    // 1. 查询顾问基本信息
    const { count, rows: advisors } = await Advisor.findAndCountAll({
        attributes: ['id', 'userName', 'bio', 'totalOrderCnt', 'score'],
        limit: pageSize,
        offset,
        raw: true,
    });

    if (advisors.length === 0) {
        return { count: 0, advisors: [] };
    }

    // 2. 批量取出顾问ID
    const advisorIds = advisors.map(a => a.id);

    // 3. 查询各顾问的服务（取 serviceType=1）
    const services = await Service.findAll({
        where: { advisorId: advisorIds, serviceType: 1 },
        attributes: ['advisorId', 'price'],
        raw: true,
    });

    // 4. 组合顾问信息 + 价格
    const advisorsWithPrice = advisors.map(advisor => {
        const service = services.find(s => s.advisorId === advisor.id);
        return {
            ...advisor,
            price: service ? service.price : null,
        };
    });

    return { count, advisors: advisorsWithPrice };
}

async function getAdvisorDetailService(id) {
    const advisorId = Number(id);

    // 1) 顾问信息（注意使用模型字段名 aboutMe；新增 completedOrderCnt 便于计算完成率）
    const advisor = await Advisor.findByPk(advisorId, {
        attributes: [
            'id',
            'userName',
            'bio',
            'aboutMe',
            'score',
            'commentCnt',
            'totalOrderCnt',
            'completedOrderCnt'
        ],
        raw: true,
    });

    if (!advisor) throw new ApiError('顾问不存在');

    // 2) 完成率 on_time = completed / total（保留两位小数；分母为0则为0）
    const total = Number(advisor.totalOrderCnt || 0);
    const completed = Number(advisor.completedOrderCnt || 0);
    const on_time = total > 0 ? Number((completed / total).toFixed(2)) : 0;

    // 3) 顾问服务列表
    const services = await Service.findAll({
        where: { advisorId },
        raw: true,
    });

    // 4) 评论列表（按评论时间倒序）
    // 为了让 getter 生效，这里用 raw: false
    const commentRows = await OrderComment.findAll({
        where: { advisorId },
        attributes: [
            'id',
            'userId',
            'advisorId',
            'rating',
            'content',
            'commentAt',
            'replyContent',
            'replyAt'
        ],
        order: [[Sequelize.col('commentAt_ms'), 'DESC']], // 最新在前
        raw: false,
    });

    const commentsPlain = commentRows.map(r => r.get({ plain: true }));

    // 4.1) 批量拉取用户昵称
    const userIds = [...new Set(commentsPlain.map(c => c.userId))];
    let userMap = new Map();
    if (userIds.length) {
        const users = await User.findAll({
            where: { id: { [Op.in]: userIds } },
            attributes: ['id', 'userName'],
            raw: true,
        });
        userMap = new Map(users.map(u => [u.id, u.userName]));
    }

    // 4.2) 组装评论返回结构
    const comments = commentsPlain.map(c => ({
        id: c.id,
        userId: c.userId,
        user_name: userMap.get(c.userId) || '',
        advisorId: c.advisorId,
        rating: Number(c.rating),
        content: c.content || '',
        commentAt: c.commentAt,
        advisorReply: c.replyContent ?? null,
        replyAt: c.replyAt ?? null,
    }));

    // 5) 返回
    return {
        advisor: {
            ...advisor,
            on_time,
        },
        services,
        comments,
    };
}


//用户收藏顾问（新增“顾问是否存在”校验）
async function favoriteAdvisorService({ userId, advisorId, note = null }) {
  // 并发查询：顾问是否存在 + 是否已有收藏记录
  const [advisor, existed] = await Promise.all([
    Advisor.findByPk(advisorId, { attributes: ['id'] }),
    AdvisorFavorite.findOne({ where: { userId, advisorId } }),
  ]);

  if (!advisor) {
    throw ApiError.BadRequest('该顾问不存在');
  }

  if (existed) {
    if (Number(existed.isDeleted) === 0) {
      throw ApiError.BadRequest('已收藏该顾问');
    }
    // isDeleted = 1 -> 置回 0
    existed.isDeleted = 0;
    if (note !== null && note !== undefined) {
      existed.note = String(note).slice(0, 100);
    }
    await existed.save();
    return existed.get({ plain: true });
  }

  // 无记录 -> 新建
  const created = await AdvisorFavorite.create({
    userId,
    advisorId,
    note: note != null ? String(note).slice(0, 100) : null,
    isDeleted: 0,
  });

  return created.get({ plain: true });
}

//取消收藏顾问（新增“顾问是否存在”校验）
async function unfavoriteAdvisorService({ userId, advisorId }) {
  // 并发查询：顾问是否存在 + 收藏记录
  const [advisor, existed] = await Promise.all([
    Advisor.findByPk(advisorId, { attributes: ['id'] }),
    AdvisorFavorite.findOne({
      where: { userId, advisorId },
      order: [['createdAt', 'DESC']],
    }),
  ]);

  if (!advisor) {
    throw ApiError.BadRequest('该顾问不存在');
  }

  if (!existed) {
    throw ApiError.BadRequest('未收藏该用户');
  }
  if (Number(existed.isDeleted) === 1) {
    throw ApiError.BadRequest('已取消收藏该顾问');
  }

  existed.isDeleted = 1;
  await existed.save();
  return existed.get({ plain: true });
}

// 获取用户收藏的顾问列表
async function getFavoriteAdvisorsPagedService(userId, opts = {}) {
  // 1) 解析分页参数：page/pageSize 优先；否则使用 offset/limit
  let {
    page,
    pageSize,
    offset,
    limit,
  } = opts;

  // 兼容拼写 "limite"
  if (limit == null && typeof opts.limite !== 'undefined') {
    limit = Number(opts.limite);
  }

  // 标准化默认值
  const DEFAULT_PAGE_SIZE = 10;
  const usingPageMode = page != null || (offset == null && limit == null);

  if (usingPageMode) {
    page = Math.max(1, Number(page || 1));
    pageSize = Math.max(1, Number(pageSize || DEFAULT_PAGE_SIZE));
    offset = (page - 1) * pageSize;
    limit = pageSize;
  } else {
    offset = Math.max(0, Number(offset || 0));
    limit = Math.max(1, Number(limit || DEFAULT_PAGE_SIZE));
    // 同时也计算出 page/pageSize 以便统一返回
    pageSize = limit;
    page = Math.floor(offset / limit) + 1;
  }

  // 2) 统计总数
  const where = { userId, isDeleted: 0 };
  const total = await AdvisorFavorite.count({ where });

  if (total === 0) {
    return {
      list: [],
      pagination: {
        total: 0,
        page,
        pageSize,
        offset,
        limit,
        hasMore: false,
        pages: 0,
      },
    };
  }

  // 3) 分页取收藏（只取 advisorId）
  const favRows = await AdvisorFavorite.findAll({
    where,
    attributes: ['advisorId'],
    order: [['createdAt', 'DESC']], // 最近收藏靠前
    offset,
    limit,
    raw: true,
  });

  const advisorIds = [...new Set(favRows.map(f => f.advisorId))];
  if (advisorIds.length === 0) {
    return {
      list: [],
      pagination: {
        total,
        page,
        pageSize,
        offset,
        limit,
        hasMore: offset + limit < total,
        pages: Math.ceil(total / pageSize),
      },
    };
  }

  // 4) 批量查顾问信息
  const advisors = await Advisor.findAll({
    where: { id: { [Op.in]: advisorIds } },
    attributes: ['id', 'userName', 'bio', 'totalOrderCnt', 'score'],
    raw: true,
  });
  const advisorMap = new Map(advisors.map(a => [a.id, a]));

  // 5) 批量查 serviceType=1 的服务价格
  const svcRows = await Service.findAll({
    where: { advisorId: { [Op.in]: advisorIds }, serviceType: 1 },
    attributes: ['advisorId', 'price'],
    raw: true,
  });
  const priceMap = new Map(svcRows.map(s => [s.advisorId, s.price]));

  // 6) 组装返回列表（保持与分页数据对应的顺序）
  const list = favRows
    .map(f => {
      const a = advisorMap.get(f.advisorId);
      if (!a) return null;
      const price = priceMap.get(a.id);
      return {
        id: a.id,
        userName: a.userName,
        bio: a.bio,
        totalOrderCnt: Number(a.totalOrderCnt || 0),
        score: (a.score ?? 0).toString(),
        price: price != null ? String(price) : null, // serviceType=1 的价格
      };
    })
    .filter(Boolean);

  return {
    list,
    pagination: {
      total,
      page,
      pageSize,
      offset,
      limit,
      hasMore: offset + limit < total,
      pages: Math.ceil(total / pageSize),
    },
  };
}
module.exports = {
    registerService,
    updateUserProfileService,
    getAdvisorListService,
    getAdvisorDetailService,
    favoriteAdvisorService,
    unfavoriteAdvisorService,
    getFavoriteAdvisorsPagedService,
};